package com.fowo.api.syncLingxingApi.service.syncImpl;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fowo.api.datainterface.util.JsonUtil;
import com.fowo.api.entity.Product;
import com.fowo.api.syncLingxingApi.entity.TmpSyncLingxingToSpuList;
import com.fowo.api.syncLingxingApi.service.SyncBaseService;
import com.fowo.api.sys.annotation.RedisSyncLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
@Slf4j
@DS("ds24")
public class SyncSpuListServiceImpl extends SyncBaseService {

    private final static Integer MAX_LEN = 200;//分页上线

    @Resource
    private SyncLxSpuInfoServiceImpl syncLxSpuInfoService;

    public SyncSpuListServiceImpl() {
        super("spuListUrl", 200);
    }

    @RedisSyncLock(value = "SyncSpuListServiceImpl_mainLoop", timeout = 1000)
    @Transactional
    public void mainLoop(JSONObject object) throws Exception {
        long start_time_ms = System.currentTimeMillis();
        log.info("初始化操作, 清空临时表数据.");
        if (!super.initData()) {
            log.error("获取token失败.");
            return;
        }
        if (this.lxApiToken == null) return;
        int cur_offset = 0;
        int totalNum = 1;
        redisUtil.removeByPrefix(catchKey);
        final String key = StrUtil.format("{}:{}", catchKey, data_version);
        while (totalNum >= cur_offset) {
            long block_start_time_ms = System.currentTimeMillis();
            JSONObject results = this.pullLingxingData(cur_offset, MAX_LEN);
            if (ObjUtil.isNotEmpty(results) && MapUtil.getInt(results, "code") == 0) {
                totalNum = MapUtil.getInt(results, "total");
                List<TmpSyncLingxingToSpuList> tmpProductList = JsonUtil.getJsonToList(MapUtil.getStr(results, "data"), TmpSyncLingxingToSpuList.class);
                List<String> spuList = new ArrayList<>();
                for (TmpSyncLingxingToSpuList tmpPr : tmpProductList) {
                    spuList.add(tmpPr.getSpu());
                }
                List<Product> oldProducts = searchOldData(spuList);
                log.info("比较新旧数据");
                List<TmpSyncLingxingToSpuList> cmpResults = compareNewOrOldDataSpu(tmpProductList, oldProducts);
                // 插入临时表
                log.info("插入缓存，数量：" + Convert.toStr(cmpResults.size()));
                for (TmpSyncLingxingToSpuList cmpResult : cmpResults) {
                    redisUtil.ListLeftPush(key, JsonUtil.getObjectToString(cmpResult));
                }
                long currentTimeMillis = System.currentTimeMillis();
                log.info("拉取数据：" + Convert.toStr(cur_offset) + "/" + Convert.toStr(totalNum) + "。用时" +
                        Convert.toStr(currentTimeMillis - block_start_time_ms) + "毫秒。总用时" +
                        Convert.toStr(currentTimeMillis - start_time_ms) + "毫秒");
            } else {
                // MARK BUG
                log.error("拉取产品数据失败. offset=" + Convert.toStr(cur_offset) + ".");
            }
            cur_offset += MAX_LEN;
        }
        // 查询多属性产品详情
        JSONObject param = new JSONObject();
        param.put("key", key);
        syncLxSpuInfoService.mainLoop(param);
    }

    public JSONObject pullLingxingData(Integer offset, Integer length
    ) {
        Map<String, Object> requestBody = new HashMap<>();
        if (offset > 0) requestBody.put("offset", offset);
        if (length > 0) requestBody.put("length", length);
        return tryRequestLingxingApi(requestBody, super.lxApiUrl);
    }

    public List<Product> searchOldData(List<String> spus) {
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("spu", spus);
        return productService.list(queryWrapper);
    }


}
